﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharp10.GenericClass
{
    internal class GenericTypes
    {

        public static void Show()
        {
            /* Stack<Bear> bears = new Stack<Bear>();
             //Stack<Animal> animals = bears;

             ZooCleaner.Wash(bears);

             // 数组支持协变
             Bear[] bears1 = new Bear[3];
             Animal[] animals = bears1;
             animals[0] = new Camel();*/

            var bears = new Stack<Bear>();
            bears.Push(new Bear());
            IPoppable<Animal> animals = bears;
            Animal a = animals.Pop();

            IPushable<Animal> animals2 = new Stack<Animal>();
            IPushable<Bear> bears2 = animals2;
            bears2.Push(new Bear());
        }

        // 把泛型类型转换为具体类型需要两步：1 把泛型转换为object类型，2 在把object类型转为具体类型。
        StringBuilder Foo<T>(T arg)
        {
            StringBuilder sb = arg as StringBuilder;
            if (sb != null) return sb;
            return (StringBuilder)(object)arg;
        }

        int Foo2<T>(T x) => (int)(object)x;
    }

    // 声明多个重名的泛型类是可以的。
    public class Animal { }
    public class Bear : Animal { }
    public class Camel : Animal { }

    public class Stack<T> : IPoppable<T>,IPushable<T>
    {
        int position;
        T[] data = new T[100];
        public void Push(T obj) => data[position++] = obj;
        public T Pop() => data[position--];
    }

    public class ZooCleaner
    {
        //public static void Wash(Stack<Animal> animals) { }
        public static void Wash<T>(Stack<T> animals) { }
    }

    // 协变
    public interface IPoppable<out T> { T Pop(); }
    // 逆变
    public interface IPushable<in T> { void Push(T obj); }
}
